/*


	jQuery plugin: formManualValidation
	Author: Ian Hart at Grand Union [ianh@thegrandunion.com]


	What?
	=====
	Validate forms for email addresses, passwords, file types and required fields.


	How?
	====
	Required form elements should be given the class "req", e.g:
	
		<input type="text" name="address" id="address" class="req" />
	
	The plugin is then initialised in the JS like so:
	
		$('#my-form').manualFormValidation();
		
	Use the options below to change email or password elements and specify cases 
	for "this or that" inputs and file types. E.g:
	
		$('#my-form').manualFormValidation({
			'or' : [$('#house-number, #house-name')],
			'filetype' : [
				{
					$id : $('#pic-upload'),
					types : ['jpg','png','gif']
				}				
			]
		});


	Options
	=======
	email:
		$standard: The jQuery element of the email input.
		$confirm: The jQuery element of the email confirmation input.
	password:
		$standard: The jQuery element of the password input.
		$confirm: The jQuery element of the password confirmation input.
	or: An array of jQuery elements where one of the elements must have a value.
	filetype: An array of jQuery elements and an array of allowed file extensions.
	
	
	Dependencies
	============
	
	- jQuery 1.3.2 or higher (jquery.com)
	
	
*/
(function($){

	$.fn.formManualValidation = function(settings){

		var G = {
			config : {
				'email' : {
					$standard : $('#email'),
					$confirm : $('#email-confirm')
				},
				'password' : {
					$standard : $('#password'),
					$confirm : $('#password-confirm')
				},
				'or' : [],
				'filetype' : [],
				'msg' : {
					'empty' : '<p>Please make sure the following fields are complete:</p>',
					'email' : '<p>Please make sure your email addresses match.</p>',
					'password' : '<p>Please make sure your passwords match.</p>',
					'emailInvalid' : '<p>Please make sure your email address is valid.</p>',
					'filetype' : '<p>Please select a valid file type for:</p>'
				}
			},
			$this : this,
			'msg' : '',
			flagFail : false,
			callback : function(){},
			emailRegex : /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/
		};

		if(settings){ $.extend(G.config, settings); }


		function init(){

			G.$this.submit(function(){
			
				G.msg = '';
				G.flagFail = false;
				
				$('.req.error, .error', G.$this).removeClass('error');
				$('.req[value=""]', G.$this).addClass('error');
				
				validateEmail();
				validateMatch();
				validateEmpty();
				validateFileType();

				if(G.flagFail === true){
					doCallback();
					return false;
				}

			});

		}
		
		
		function validateEmail(){

			if(G.config.email.$standard.length){

				if(G.emailRegex.test($(G.config.email.$standard).attr('value')) === false && G.config.email.$standard.attr('value') !== ''){
					G.flagFail = true;
					G.config.email.$standard.addClass('error');
					G.msg += G.config.msg.emailInvalid;
				}
				else if(G.config.email.$standard.attr('value') !== G.config.email.$confirm.attr('value')){
					G.flagFail = true;
					G.config.email.$standard.addClass('error');
					G.config.email.$confirm.addClass('error');
					G.msg += G.config.msg.email;
				}
			
			}

		}
		
		
		function validateMatch(){
		
			// Check IDs have been specified.
			if(G.config.password.$standard.length && G.config.password.$confirm.length){
				if(G.config.password.$standard.attr('value') !== G.config.password.$confirm.attr('value')){
					G.flagFail = true;
					G.config.password.$standard.addClass('error');
					G.config.password.$confirm.addClass('error');
					G.msg += G.config.msg.password;
				}
			}
		
		}
		
		
		function validateFileType(){
			var ext, val, flagFail, msg = '';

			if(G.config.filetype.length > 0 && G.config.filetype[0].$id.length){

				$.each(G.config.filetype, function(){
	
					flagFail = false;
					val = this.$id.attr('value');
					
					if(val.length > 3){
	
						ext = val.substr(val.lastIndexOf('.')+1, val.length);
						if($.inArray(ext, this.types) == -1){
							msg += '<li>' + $('label[for='+this.$id.attr('id')+']').text() + '</li>';
						}
					}
	
				});
				
				if(msg !== ''){
					G.flagFail = true;
					G.msg += G.config.msg.filetype + '<ul>'+msg+'</ul>';
				}
			
			}
		}
		
		
		function validateEmpty(){
		
			var msg = '';
		
			$('.req', G.$this).each(function()
			{
				if($(this).attr('type') === 'checkbox' && !$(this).attr('checked')){
					msg += '<li>Confirm &ldquo;' + $('label[for='+$(this).attr('id')+']').text() + '&rdquo;</li>';
				}
				if($(this).attr('value') === ''){
					$(this).addClass('error');
					msg += '<li>' + $('label[for='+$(this).attr('id')+']').text() + '</li>';
				}
			});
			
			msg += validateOr();
			msg = msg.replace(/\* /g, '');
			msg = msg.replace(/ \(required field\)/ig, '');			

			if(msg !== ''){
				G.flagFail = true;
				G.msg += G.config.msg.empty + '<ul>'+msg+'</ul>';
			}
		
		}
		
		
		function validateOr(){
		
			var len = G.config.or.length,
				tempArr = [],
				hasValue,
				msg = '',
				tempMsg = '';

			for(i=0; i<len; i++){
			
				hasValue = false;
				tempMsg = '';

				G.config.or[i].each(function(){
					if($(this).attr('value') !== ''){
						hasValue = true;
					}
					tempMsg += ' or ' + $('label[for='+$(this).attr('id')+']').text().replace('Or ', '');
				});
				
				if(hasValue === false){
					G.config.or[i].addClass('error');
					msg += '<li>' + tempMsg.substring(4) + '</li>';
				}
				
			}
			
			return msg;
		
		}
		
		
		function doCallback(){
		
			G.config.callback(G.msg);
		
		}
		
		
		init();

		
		return this;
		

	};

})(jQuery);